home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / standards / sgml / nist / parse1 / dtdattr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-09-13  |  23.8 KB  |  765 lines

  1. /* National Institute of Standards and Technology (NIST)
  2. /* National Computer System Laboratory (NCSL)
  3. /* Office Systems Engineering (OSE) Group
  4. /* ********************************************************************
  5. /*                            D I S C L A I M E R
  6. /*                              (March 8, 1989)
  7. /*  
  8. /* There is no warranty for the NIST NCSL OSE SGML parser and/or the NIST
  9. /* NCSL OSE SGML parser validation suite.  If the SGML parser and/or
  10. /* validation suite is modified by someone else and passed on, NIST wants
  11. /* the parser's recipients to know that what they have is not what NIST
  12. /* distributed, so that any problems introduced by others will not
  13. /* reflect on our reputation.
  14. /* 
  15. /* Policies
  16. /* 
  17. /* 1. Anyone may copy and distribute verbatim copies of the SGML source
  18. /* code as received in any medium.
  19. /* 
  20. /* 2. Anyone may modify your copy or copies of SGML parser source code or
  21. /* any portion of it, and copy and distribute such modifications provided
  22. /* that all modifications are clearly associated with the entity that
  23. /* performs the modifications.
  24. /* 
  25. /* NO WARRANTY
  26. /* ===========
  27. /* 
  28. /* NIST PROVIDES ABSOLUTELY NO WARRANTY.  THE SGML PARSER AND VALIDATION
  29. /* SUITE ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
  30. /* EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  31. /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  32. /* THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS
  33. /* WITH YOU.  SHOULD THE SGML PARSER OR VALIDATION SUITE PROVE DEFECTIVE,
  34. /* YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
  35. /* 
  36. /* IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL NIST BE LIABLE FOR
  37. /* DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL,
  38. /* INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
  39. /* INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
  40. /* BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A
  41. /* FAILURE OF THE PROGRAM TO OPERATE WITH PROGRAMS NOT DISTRIBUTED BY
  42. /* NIST) THE PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF
  43. /* SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
  44. */
  45.  
  46. /************************************************************************/
  47. /*   TITLE:          SGML PARSER                                        */
  48. /*   SYSTEM:         DTD PROCESSOR                                      */
  49. /*   SUBSYSTEM:                                                         */
  50. /*   SOURCE FILE:    DTDATTR.C                                          */
  51. /*   AUTHOR:         Jim Heath                                          */
  52. /*                                                                      */
  53. /*   DATE CREATED:                                                      */
  54. /*   LAST MODIFIED:                                                     */
  55. /*                                                                      */
  56. /*                  REVISIONS                                           */
  57. /*   WHEN      WHO            WHY                                       */
  58. /************************************************************************/
  59. #include <stdio.h>
  60. #include <setjmp.h>
  61. #include <memory.h>
  62. #include <unistd.h>
  63.  
  64. #include "qntyset.h"
  65. #include "dtd.h"
  66. #include "dtdfncs.h"
  67. #include "dtdglbl.h"
  68. #include "dtddefs.h"
  69. long lseek();
  70. static ATTRIBSTRUCT attrib;
  71. static int decltokencount, totdfltcount;
  72. /* ============================================================ */
  73. int doattlist()
  74. {
  75.    REGISTER int j;
  76.    int eltcount, namegrp = FALSE;
  77.    char *nmptr, eltname[NAMELEN + 1], *eltnmptr;
  78.    char tempnames[GRPCNT * (NAMELEN + 1)];
  79.  
  80.    totdfltcount = 0;
  81.    memset(&attrib, '\0', sizeof(attrib));
  82.    memset(eltname, '\0', sizeof(eltname));
  83. #ifdef OLD
  84. #else
  85.     memset(tempnames, ' ', sizeof(tempnames));
  86. #endif
  87.    if ((j = INPPS()) == EOF)
  88.       terminate(1, "EOF found in ATTLIST declaration");
  89.    if (j < 1)
  90.       syntxerr("Expected PS+ at this point");
  91.    ADDCHAR(SPACE);
  92.    nmptr = eltname;
  93.    if((j = INPNAME(&nmptr, NAMELEN, TOUPPER)) == EOF)
  94.       terminate(1, "EOF found in ATTLIST declaration");
  95.    if (j < GOOD) {
  96.       namegrp = TRUE;
  97.       eltcount = getnamegrp(tempnames, ISALPHA, isnmchar);
  98.       eltnmptr = tempnames;
  99.    }
  100.    else {
  101.       ADDSTRING(eltname);
  102.       eltcount = 1;
  103.    }
  104.  
  105.    if ((j = INPPS()) == EOF)
  106.       terminate(1, "EOF found in ATTLIST declaration");
  107.    if (j < 1)
  108.       syntxerr("Expected PS+ at this point");
  109.    ADDCHAR(SPACE);
  110.    safewrite(attrtemp, (char *)&eltcount, sizeof(eltcount));
  111.    if (namegrp == TRUE)
  112.       for (j = 0; j < eltcount; j++, eltnmptr += NAMELEN + 1)
  113.          safewrite(attrtemp, (char *)eltnmptr, NAMELEN + 1);
  114.    else
  115.       safewrite(attrtemp, (char *)eltname, sizeof(eltname));
  116.    return(doattlist2());
  117. }
  118. /* ============================================================ */
  119. int doattlist2()
  120. {
  121.    char *nmptr;
  122.    REGISTER int j;
  123.    int attindex = 0;
  124.    char attnames[ATTCNT] [NAMELEN + 1];
  125.    char decltokens[ATTCNT * (NAMELEN + 1)];
  126.    int declvalcode, dfltvalcode, k,
  127.    notatcount = 0, idcount = 0, attrcount = 0;
  128.  
  129.    memset (decltokens, '\0', sizeof(decltokens));
  130.    decltokencount = 0;
  131.    while(1) {
  132. #ifdef OLD
  133. #else
  134.         memset(attrib.Agrpnames, '\0', sizeof(attrib.Agrpnames));
  135. #endif
  136.       ADDSTRING("\015\012          ");
  137.       nmptr = attrib.Aname;
  138.  
  139.       if((j = INPNAME(&nmptr, NAMELEN, TOUPPER)) == EOF)
  140.          terminate(1, "EOF found in ATTLIST declaration");
  141.       if (j >= GOOD){
  142.          ADDSTRING(attrib.Aname);
  143.          for (k = 0; k < attindex; k++)
  144.             if (strcmp(attnames[k], attrib.Aname) == 0)
  145.                syntxerr("duplicate attribute name in ATTLIST");
  146.          if (attindex > ATTCNT)
  147.             syntxerr("ATTCNT exceeded in ATTLIST");
  148.          strcpy(attnames[attindex++], attrib.Aname);
  149.       }
  150.       else
  151.          syntxerr("expected valid attribute name");
  152.       for (j = strlen(attrib.Aname); j < NAMELEN; j++)
  153.          attrib.Aname[j] = ' ';
  154.  
  155.       declvalcode = getdeclvalcode(decltokens);
  156.       if (declvalcode == KW_ID)
  157.          if(idcount++ > 0)
  158.             syntxerr("ID can be declared only once in an ATTLIST");
  159.       if (declvalcode == KW_NOTATION) {
  160.          if(notatcount++ > 0)
  161.             syntxerr("NOTATION can be declared only once in an ATTLIST");
  162.          if ((j = INPPS()) == EOF)
  163.             terminate(1, "EOF found in ATTLIST declaration");
  164.          ADDCHAR(SPACE);
  165.          (void) getdeclgroup( decltokens);
  166.       }
  167.       /* convert declared value code */
  168.       cvrtdeclcode (declvalcode);
  169.       dfltvalcode = getdfltvalcode();
  170.  
  171.       /* convert default value code */
  172.       cvrtdfltcode(dfltvalcode);
  173.  
  174.       analyzedflt(declvalcode, dfltvalcode, attrib.Adfltval);
  175.       if (doattlist3(&attrcount))
  176.          return(attrcount);
  177.    }
  178. }
  179. /* ============================================================ */
  180. int doattlist3(attrcount)
  181. int *attrcount;
  182. {
  183.    static long position;
  184.    long position2;
  185.    int j;
  186.    if (*attrcount == 0) {
  187.       if((position = lseek(attrtemp, 0L, SEEK_CUR)) == -1L)
  188.          terminate(1,"error on lseek");
  189.       safewrite(attrtemp, attrcount, sizeof(int));
  190.    }
  191.    if ((*attrcount)++ >= ATTCNT)
  192.       syntxerr("too many attributes in this ATTLIST");
  193.  
  194.  
  195.    safewrite(attrtemp, attrib.Aname, sizeof(attrib.Aname));
  196.    safewrite(attrtemp, &attrib.Adeclcode, sizeof(attrib.Adeclcode));
  197.    safewrite(attrtemp, &attrib.Adfltcode, sizeof(attrib.Adfltcode));
  198.    safewrite(attrtemp, attrib.Adfltval, sizeof(attrib.Adfltval));
  199.    safewrite(attrtemp, &attrib.Agrpcount, sizeof(attrib.Agrpcount));
  200.    for ( j = 0; j < attrib.Agrpcount; j++){
  201.       safewrite(attrtemp, attrib.Agrpnames[j].lnames, NAMELEN + 1);
  202.    }
  203.  
  204.    if ((j = INPPS()) == EOF)
  205.       terminate(1, "EOF found in ATTLIST declaration");
  206.    if ((j = jgetc()) == MDC){
  207.       ADDCHAR(MDC);
  208.       if((position2 = lseek(attrtemp, 0L, SEEK_CUR)) == -1L)
  209.          terminate(1,"error on lseek");
  210.       if ((position = lseek(attrtemp, position, SEEK_SET)) == -1L)
  211.          terminate(1,"error on lseek");
  212.       safewrite(attrtemp, attrcount, sizeof(int));
  213.       if((position = lseek(attrtemp, position2, SEEK_SET)) == -1L)
  214.          terminate(1,"error on lseek");
  215.       if ((*attrcount + decltokencount) > ATTCNT)
  216.          syntxerr("total number of names and name tokens exceeds ATTCNT");
  217.       return(*attrcount);
  218.    }
  219.    ADDCHAR(' ');
  220.    jungetc(j);
  221.    return(0);
  222. }
  223. /* =========================================================== */
  224. static int getdeclvalcode(decltokens)
  225. char *decltokens;
  226. {
  227.    REGISTER int j;
  228.    char temp[NAMELEN+1], *tmpptr = temp;
  229.  
  230.    if ((j = INPPS()) == EOF)
  231.       terminate(1, "EOF found in ATTLIST declaration");
  232.    if (j < 1)
  233.       syntxerr("Expected PS+ at this point");
  234.    ADDCHAR(SPACE);
  235.    if ((j = INPNMTOKEN(&tmpptr, NAMELEN, TOUPPER)) == EOF)
  236.       terminate(1, "EOF in ATTRIBUTE declaration");
  237.    if (j > GOOD)
  238.       ADDSTRING(temp);
  239.    else
  240.       j = getdeclgroup(decltokens);
  241.    return(j);
  242. }
  243. /* =========================================================== */
  244. static int getdeclgroup(decltokens)
  245. char *decltokens;
  246. {
  247.    char tempnames[GRPCNT * (NAMELEN + 1)], *dgrpptr = tempnames, *dptr;
  248.    REGISTER int j;
  249.  
  250.    attrib.Agrpcount = getnamegrp(tempnames, isnmchar, isnmchar);
  251.    if (attrib.Agrpcount > GRPCNT)
  252.       terminate(1, "too many declared values!");
  253.    for (j = 0; j < attrib.Agrpcount; j++, dgrpptr += (NAMELEN + 1)) {
  254.       strcpy(attrib.Agrpnames[j].lnames, dgrpptr);
  255.       for (dptr = decltokens; strlen(dptr) != 0; dptr += (NAMELEN + 1)) {
  256.          if(memcmp(dgrpptr, dptr, NAMELEN + 1) == 0)
  257.             syntxerr("duplicate declared values in same ATTLIST");
  258.       }
  259.       strcpy(dptr, dgrpptr);
  260.       if (++decltokencount >= ATTCNT)
  261.          syntxerr("ATTCNT exceeded in ATTLIST");
  262.    }
  263.    return(KW_GROUP);
  264. }
  265. /* =========================================================== */
  266. static int getdfltvalcode()
  267. {
  268.    REGISTER int j;
  269.    char namearray[NAMELEN+1], *tmpptr = namearray;
  270.  
  271.    if ((j = INPPS()) == EOF)
  272.       terminate(1, "EOF found in ATTLIST declaration");
  273.    if (j < 1)
  274.       syntxerr("Expected PS+ at this point");
  275.    ADDCHAR(SPACE);
  276.    if ((j = INPRNINAME(&tmpptr, NAMELEN, TOUPPER)) == EOF)
  277.       terminate(1, "EOF in ATTRIBUTE declaration");
  278.    if (j >= GOOD)
  279.       switch (j) {
  280.       case KW_FIXED:
  281.          ADDSTRING(namearray);
  282.          ADDCHAR(' ');
  283.          if (INPPS() == EOF)
  284.             terminate(1, "EOF found in ATTLIST declaration");
  285.          (void) getdfltlit();
  286.          return(j);
  287.       case KW_REQUIRED:
  288.       case KW_CURRENT:
  289.       case KW_CONREF:
  290.       case KW_IMPLIED:
  291.          ADDSTRING(namearray);
  292.          return (j);
  293.       default:
  294.          syntxerr("Illegal default value for attribute");
  295.       }
  296.    return(getdfltlit());
  297. }
  298. /* =========================================================== */
  299. static int getdfltlit()
  300. {
  301.    char buff[LITLEN + 1], *ccptr = buff;
  302.    REGISTER char *cptr = buff;
  303.    char *src, *dest, *resptr;
  304.  
  305.    memset(buff, '\0', sizeof(buff));
  306.    if (attrib.Adeclcode == ENUM_CDATA) {
  307.       inputattrvalspec(&ccptr) ;
  308.       dest = attrib.Adfltval;
  309.       src = buff;
  310.       do {
  311.          if((*src == TAB) || (*src == RE))
  312.             *dest++ = SPACE;
  313.          else if ((*src == EE) || (*src == RS))
  314.             continue;
  315.          else
  316.             *dest++ = *src;
  317.       }       while (*src++ != '\0');
  318.    }
  319.    else {
  320.       inputattrvalspec(&ccptr) ;
  321.       dest = attrib.Adfltval;
  322.       src = buff;
  323.       do {
  324.          if((*src == TAB) || (*src == RE))
  325.             *dest++ = SPACE;
  326.          else if ((*src == EE) || (*src == RS))
  327.             continue;
  328.          else
  329.             *dest++ = *src;
  330.       }       while (*src++ != '\0');
  331.    }
  332.    if (attrib.Adeclcode != ENUM_CDATA && attrib.Adeclcode != ENTITY)
  333.       for (cptr = attrib.Adfltval; *cptr != '\0'; cptr++)
  334.          *cptr = TOUPPER(*cptr);
  335.    /* this code checks to make sure the default value on */
  336.    /* entity is a valid general entity name */
  337.    if (attrib.Adeclcode == ENTITY) {
  338.       cptr = attrib.Adfltval;
  339.       if ((strcmp(cptr,"#DEFAULT")) == 0 || 
  340.           (search(GEN_ENT_NAME, cptr, &resptr)) == ILLCHAR)
  341.          syntxerr("default value must be a valid general entity name\n");
  342.    }
  343.    return(KW_LIT);
  344. }
  345. /* =========================================================== */
  346. static void analyzedflt(declval, dfltval, dflt)
  347. int declval;
  348. char *dflt;
  349. {
  350.    char temp[128];
  351.    switch(declval) {
  352.    case KW_CDATA:
  353.       return;
  354.    case KW_IDREF:
  355.    case KW_NAME:
  356.       if (dfltval == KW_LIT)
  357.          validate(dflt, 1, ISALPHA, isnmchar);
  358.       return;
  359.    case KW_IDREFS:
  360.    case KW_NAMES:
  361.       if (dfltval == KW_LIT)
  362.          validate(dflt, 0, ISALPHA, isnmchar);
  363.       return;
  364.    case KW_NUMBER:
  365.       if (dfltval == KW_LIT)
  366.          validate(dflt, 1, ISDIGIT, ISDIGIT);
  367.       return;
  368.    case KW_NUMBERS:
  369.       if (dfltval == KW_LIT)
  370.          validate(dflt, 0, ISDIGIT, ISDIGIT);
  371.       return;
  372.    case KW_NMTOKEN:
  373.       if (dfltval == KW_LIT)
  374.          validate(dflt, 1, isnmchar, isnmchar);
  375.       return;
  376.    case KW_NMTOKENS:
  377.       if (dfltval == KW_LIT)
  378.          validate(dflt, 0, isnmchar, isnmchar);
  379.       return;
  380.    case KW_NUTOKEN:
  381.       if (dfltval == KW_LIT)
  382.          validate(dflt, 1, ISDIGIT, isnmchar);
  383.       return;
  384.    case KW_NUTOKENS:
  385.       if (dfltval == KW_LIT)
  386.          validate(dflt, 0, ISDIGIT, isnmchar);
  387.       return;
  388.    case KW_GROUP:
  389.    case KW_NOTATION:
  390.       if (dfltval == KW_LIT)
  391.          grpvalidate(dflt);
  392.       return;
  393.    case KW_ID:
  394.       if((dfltval != KW_REQUIRED) && (dfltval != KW_IMPLIED)) {
  395.          strcpy (temp,"DEFAULT VALUE must be #REQUIRED or #IMPLIED when ");
  396.          strcat (temp,"DECLARED VALUE is ID\n");
  397.          syntxerr(temp);
  398.       }
  399.    }
  400. }
  401.  
  402. /* =========================================================== */
  403. static void cvrtdeclcode(tdeclval)
  404. int tdeclval;
  405. {
  406.    switch(tdeclval) {
  407.    case KW_GROUP:
  408.       attrib.Adeclcode = GROUP;
  409.       break;
  410.    case KW_CDATA:
  411.       attrib.Adeclcode = ENUM_CDATA;
  412.       break;
  413.    case KW_ENTITY:
  414.       attrib.Adeclcode = ENTITY;
  415.       break;
  416.    case KW_ID:
  417.       attrib.Adeclcode = ID;
  418.       break;
  419.    case KW_IDREF:
  420.       attrib.Adeclcode = IDREF;
  421.       break;
  422.    case KW_NAME:
  423.       attrib.Adeclcode = NAME;
  424.       break;
  425.    case KW_NMTOKEN:
  426.       attrib.Adeclcode = NMTOKEN;
  427.       break;
  428.    case KW_NUTOKEN:
  429.       attrib.Adeclcode = NUTOKEN;
  430.       break;
  431.    case KW_IDREFS:
  432.       attrib.Adeclcode = IDREFS;
  433.       break;
  434.    case KW_NAMES:
  435.       attrib.Adeclcode = NAMES;
  436.       break;
  437.    case KW_NMTOKENS:
  438.       attrib.Adeclcode = NMTOKENS;
  439.       break;
  440.    case KW_NUTOKENS:
  441.       attrib.Adeclcode = NUTOKENS;
  442.       break;
  443.    case KW_NOTATION:
  444.       attrib.Adeclcode = NOTATION;
  445.       break;
  446.    case KW_NUMBER:
  447.       attrib.Adeclcode = NUMBER;
  448.       break;
  449.    case KW_NUMBERS:
  450.       attrib.Adeclcode = NUMBERS;
  451.       break;
  452.    default:
  453.       syntxerr("illegal declared value in ATTLIST");
  454.    }
  455. }
  456. /* =========================================================== */
  457. static void cvrtdfltcode(tdfltval)
  458. int tdfltval;
  459. {
  460.    switch (tdfltval) {
  461.    case KW_REQUIRED:
  462.       attrib.Adfltcode = A_REQD;
  463.       break;
  464.    case KW_FIXED:
  465.       attrib.Adfltcode = A_FIXED;
  466.       break;
  467.    case KW_CURRENT:
  468.       attrib.Adfltcode = A_CURRENT;
  469.       break;
  470.    case KW_LIT:
  471.       attrib.Adfltcode = A_UNFIXED;
  472.       break;
  473.    case KW_IMPLIED:
  474.       attrib.Adfltcode = A_IMPLIED;
  475.       break;
  476.    case KW_CONREF:
  477.       attrib.Adfltcode = A_CONREF;
  478.       break;
  479.    }
  480. }
  481. /* =========================================================== */
  482. static void validate(buff, maxcount, firsttest, othertest)
  483. char *buff;
  484. int maxcount;
  485. int (*firsttest)(), (*othertest)();
  486. {
  487.    int itemcount = 0;
  488.    char outbuf[512], *temp;
  489.    REGISTER char *src = buff, *dest = outbuf;
  490.    int normlen = NORMSEP ;  /* one initial normsep */
  491.  
  492.    if (*src <= ' ')
  493.       syntxerr("SEPARATOR not allowed");
  494.    goto GETITEM;
  495.    while (*src != '\0') {
  496.       if (*src <= ' ') {
  497.          *dest++ = *src++;
  498.          *dest = '\0';
  499.          while (*src <= ' ')
  500.             src++;
  501.       }
  502. GETITEM:
  503.       for (temp = dest; *src > ' ';) {
  504.          *dest++ = *src++;
  505.          *dest = '\0';
  506.       }
  507.       if (temp != dest) {
  508.          if (strlen(temp) > NAMELEN)
  509.             syntxerr("item too long in DEFAULT VALUE FIELD");
  510.          if (!(*firsttest)(*temp++))
  511.             syntxerr("illegal value in DEFAULT VALUE FIELD");
  512.          normlen++;   /* increment normalized length */
  513.          while (*temp != '\0') {
  514.             if (!(*othertest)(*temp++))
  515.                syntxerr("illegal value in DEFAULT VALUE FIELD");
  516.             normlen++;   /* increment normalized length */
  517.          }
  518.          if ((++itemcount > maxcount) && (maxcount != 0))
  519.             syntxerr("too many items in ATTRIBUTE VALUE SPECIFICATION");
  520.          normlen += NORMSEP ;  /* one normsep for every item in list */
  521.       }
  522.    }
  523.    if (normlen > LITLEN)
  524.       syntxerr("normalized length of DEFAULT VALUE FIELD exceeds LITLEN");
  525.    if (itemcount){
  526.       totdfltcount += itemcount;
  527.       return;
  528.    }
  529.    syntxerr("DEFAULT VALUE FIELD is empty!");
  530. }
  531. /* =========================================================== */
  532. static void grpvalidate(buff)
  533. char *buff;
  534. {
  535.    int j, itemcount = 0;
  536.    char outbuf[512];
  537.    REGISTER char *src = buff, *dest = outbuf;
  538.  
  539.    if (*src <= ' ')
  540.       syntxerr("SEPARATOR not allowed");
  541.    goto GETITEM;
  542.    while (*src != '\0') {
  543.       while (*src <= ' ')
  544.          src++;
  545. GETITEM:
  546.       for (dest = outbuf; *src != '\0'; ) {
  547.          if (*src <= ' ')
  548.             break;
  549.          *dest++ = *src++;
  550.       }
  551.       *dest = '\0';
  552.       for (j = 0; j < attrib.Agrpcount ;j++) {
  553.          if(strcmp(outbuf, attrib.Agrpnames[j].lnames) == 0)
  554.             goto FOUNDIT;
  555.       }
  556.       syntxerr("DEFAULT VALUE does not agree with DECLARED VALUE");
  557. FOUNDIT:
  558.       itemcount++;
  559.    }
  560.    if (itemcount){
  561.       totdfltcount += itemcount;
  562.       return;
  563.    }
  564.    syntxerr("DEFAULT VALUE FIELD is empty!");
  565. }
  566. /* =========================================================== */
  567. /* ============================================================ */
  568. /* inputattrvalsspec() inputs an attribute value specification  */
  569. /* delimeted by  either  LIT's or LITA's.  It only recognizes   */
  570. /* ERO's and CRO's as mark-up due to the standards definition   */
  571. /* of replaceable character data.                               */
  572. /* ============================================================ */
  573. void inputattrvalspec(litptr)
  574. char **litptr;
  575. {
  576.    int delimeter, synkey, len = 0;
  577.    REGISTER int c, d;
  578.    char *lptr = *litptr;
  579.    int refflag = 0; /* flag if 1 => entity reference found in */
  580.    /*              literal with unmatch EE */
  581.    /*      if 0 => no unmatched reference currently in */
  582.    /*              literal */
  583.  
  584.    if((c = jgetc()) == EOF)
  585.       terminate(1, "End of File found while processing ATTLIST");
  586.    /* if LIT then delimeter is LIT */
  587.    if(c == LIT)
  588.       delimeter = LIT;
  589.       /* else delimeter is LITA */
  590.    else
  591.       if(c == LITA)
  592.          delimeter = LITA;
  593.       else{
  594.          ADDCHAR(c);
  595.          jungetc(c);
  596.          syntxerr("Delimeter not found in attribute value specification");
  597.       }
  598.    /* while closing delimeter not found ...*/
  599.    while((c = jgetc()) != delimeter){
  600.       switch ((char) c){
  601.       case EE:
  602.          /* EE found not matching any existing reference within 
  603.                                                          attribute value specification */
  604.          if(refflag == 0)
  605.             syntxerr("EE found terminating reference not occurring within attribute value specification");
  606.          refflag = 0;
  607.          break;
  608.          /* if ERO, then check if entity reference */
  609.       case ERO:
  610.          if ((c = jgetc()) == EOF)
  611.             terminate(1, "End of File found while processing ATTLIST declaration");
  612.          /* if reference ... */
  613.          if(ISALPHA(c)){
  614.             jungetc(c);
  615.             /* call procedure to resolve entity reference within */
  616.             /* replaceable parameter data */
  617.             synkey = reslvgref(&lptr, &len);
  618.             if ((synkey==KW_CDATA || synkey==KW_SDATA)
  619.                 && attrib.Adeclcode != ENUM_CDATA)
  620.                syntxerr("A CDATA or SDATA entity must be referenced where character data can occur");
  621.             if (synkey == KW_CDATA || synkey ==  KW_SDATA)
  622.                len += 2;
  623.             /* set flag to unmatched reference found in attribute value specification */
  624.             refflag = 1;
  625.          }
  626.          else if(c == '#') {
  627.             if ((d = jgetc()) == EOF)
  628.                terminate(1, "End of File found while interpreting parameter literal");
  629.             if(ISDIGIT(d) || isnmstrt(d)) {
  630.                jungetc(d);
  631.                /* if CRO, then call procedure to resolve char reference */
  632.                reslvcharref(&lptr, &len);
  633.             }
  634.             else{
  635.                *lptr++ = '&';
  636.                *lptr++ = c;
  637.                *lptr++ = d;
  638.                *lptr = '\0';
  639.                len += 3;
  640.             }
  641.          }
  642.          else{
  643.             /* otherwise, no reference, so treat ERO as char data */
  644.             *lptr++ = ERO;
  645.             *lptr++ = c;
  646.             *lptr = '\0';
  647.             len += 2;
  648.          }
  649.          break;
  650.          /* default => char data */
  651.       default:
  652.          *lptr++ = c;
  653.          *lptr = '\0';
  654.          len++;
  655.          break;
  656.       }
  657.       /* if length of interpreted literal exceeds LITLEN then ERROR */
  658.       if(len > LITLEN){
  659.          ADDCHAR(LIT);
  660.          ADDSTRING(*litptr);
  661.          syntxerr("LITLEN is exceeded in attribute value specification");
  662.       }
  663.    }
  664.    ADDCHAR(LIT);
  665.    ADDSTRING(*litptr);
  666.    ADDCHAR(LIT);
  667.    *litptr = lptr;
  668. }
  669.  
  670. /* =========================================================== */
  671. /* ============================================================ */
  672. /* reslgref() resolves general entity references within         */
  673. /* replaceable character data. It inputs the reference name,    */
  674. /* searches a table on the name, and adds then entity text to   */
  675. /* the interpreted literal string.                              */
  676. /* ============================================================ */
  677. int reslvgref(litptr, lenptr)
  678. char **litptr;
  679. int *lenptr;
  680. {
  681.    REGISTER char *lptr = *litptr;
  682.    char namearray[NAMELEN + 1], *nameptr = namearray;
  683.    REGISTER int c;
  684.    int len;
  685.    char *resptr;
  686.    int synkey;
  687.  
  688.    /* input name */
  689.    if(INPNAME(&nameptr, NAMELEN, noxlat) >= GOOD){
  690.       nameptr = namearray;
  691.       synkey = search(GEN_ENT_NAME, nameptr, &resptr);
  692.       switch(synkey){
  693.       case ILLCHAR:
  694.          syntxerr("Entity reference not found in table");
  695.          break;
  696.          /* if syntactic literal is NULL, then entity text consists of */
  697.          /* parameter literal only */
  698.       case NULL:
  699.       case KW_CDATA:
  700.       case KW_SDATA:
  701.          strcat(lptr, resptr);
  702.          len = strlen(resptr);
  703.          lptr += len;
  704.  
  705.          *lptr++ = EE;
  706.          *lptr = '\0';
  707.  
  708.          break;
  709.       case KW_STARTTAG:
  710.          strcat(lptr, "<");
  711.          strcat(lptr, resptr);
  712.          strcat(lptr, ">");
  713.          len = strlen(resptr) + 2;
  714.          lptr += len;
  715.          *lptr++ = EE;
  716.          *lptr = '\0';
  717.          break;
  718.       case KW_ENDTAG:
  719.          strcat(lptr, "</");
  720.          strcat(lptr, resptr);
  721.          strcat(lptr, ">");
  722.          len = strlen(resptr) + 3;
  723.          lptr += len;
  724.          *lptr++ = EE;
  725.          *lptr = '\0';
  726.          break;
  727.          /* any other syntactic literal found is ERROR */
  728.       case KW_MS:
  729.          strcat(lptr, "<![");
  730.          strcat(lptr, resptr);
  731.          strcat(lptr, "]]>");
  732.          len = strlen(resptr) + 6;
  733.          lptr += len;
  734.          *lptr++ = EE;
  735.          *lptr = '\0';
  736.          break;
  737.          /* any other syntactic literal found is ERROR */
  738.       case KW_MD:
  739.          strcat(lptr, "<!");
  740.          strcat(lptr, resptr);
  741.          strcat(lptr, ">");
  742.          len = strlen(resptr) + 3;
  743.          lptr += len;
  744.          *lptr++ = EE;
  745.          *lptr = '\0';
  746.          break;
  747.          /* any other syntactic literal found is ERROR */
  748.       default:
  749.          syntxerr("Unknown or illegal syntactic literal in attribute value specification.");
  750.          break;
  751.       }
  752.    }
  753.    else
  754.       syntxerr("Reference name not found while resolving parameter entity reference.");
  755.    /* increment length of interpreted literal by length of entity text */
  756.    *lenptr = *lenptr + len;
  757.    if((c = jgetc()) == EOF)
  758.       terminate(1, "EOF found while processing ATTLIST");
  759.    if(c != REFC)
  760.       jungetc(c);
  761.    *litptr = lptr;
  762.  
  763.    return(synkey);
  764. }
  765.